/*********************************************************************
*
*  HTTPPrint.h file generation and dynamic variable parsing.
*
**********************************************************************
* File Name:       DynVar.java
* Complier:        JAVA version "1.6.0_20 and onwards"
* IDE :            NetBeans
*/

/*
Copyright (C) 2012-2023, Microchip Technology Inc., and its subsidiaries. All rights reserved.

The software and documentation is provided by microchip and its contributors
"as is" and any express, implied or statutory warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a particular
purpose and non-infringement of third party intellectual property rights are
disclaimed to the fullest extent permitted by law. In no event shall microchip
or its contributors be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to, procurement
of substitute goods or services; loss of use, data, or profits; or business
interruption) however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in any way
out of the use of the software and documentation, even if advised of the
possibility of such damage.

Except as expressly permitted hereunder and subject to the applicable license terms
for any third-party software incorporated in the software and any applicable open
source software license terms, no license or other rights, whether express or
implied, are granted under any patent or other intellectual property rights of
Microchip or any third party.
*/

package MicrochipMPFS;

import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.*;

public class DynVar {
    int offSetCounter = 0;
    int parseItrtn = 0;
    int tempFileRcrdLen = 0;
    boolean tcpipVersion6used;
    String regEx = "~(inc:[A-Za-z0-9\\ \\.-_\\/]{1,60}|[A-Za-z0-9_]{0,40}(\\([A-Za-z0-9_,\\ ]*\\))?)~";
    private static List<DynamicVariable> vars;
    //private Vector<Byte> resizeArray = new Vector(8,8);
    private Pattern parser = Pattern.compile(regEx);
    private String projectDir;

    String HTTPPRINT_H_HEADER =
        "/*********************************************************************\r\n" +
        " * File Name: HTTPPrint.h\r\n" +
        " *\r\n" +
        " * Provides callback headers and resolution for user\'s custom\r\n" +
        " * HTTP Application.\r\n" +
        " * Processor: PIC18,PIC24E, PIC24F, PIC24H, dsPIC30F, dsPIC33F, dsPIC33E,PIC32\r\n" +
        " * Compiler:  Microchip C18, C30, C32\r\n" +
        " * \r\n" +
        " * This file is automatically generated by the MPFS Utility\r\n" +
        " * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n" +
        " *\r\n" +
        " * Software License Agreement\r\n" +
        " *\r\n" +
        " * Copyright (C) 2012 Microchip Technology Inc.  All rights\r\n" +
        " * reserved.\r\n" +
        " *\r\n" +
        " * Microchip licenses to you the right to use, modify, copy, and \r\n " +
        " * distribute: \r\n" +
        " * (i)  the Software when embedded on a Microchip microcontroller or \r\n" +
        " *      digital signal controller product (\"Device\") which is \r\n" +
        " *      integrated into Licensee's product; or \r\n" +
        " * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,\r\n" +
        " *     ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device\r\n" +
        " *     used in conjunction with a Microchip ethernet controller for\r\n" +
        " *     the sole purpose of interfacing with the ethernet controller.\r\n" +
        " *\r\n" +
        " * You should refer to the license agreement accompanying this \r\n" +
        " * Software for additional information regarding your rights and \r\n" +
        " * obligations.\r\n" +
        " *\r\n" +
        " * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED \"AS IS\" WITHOUT\r\n" +
        " * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT\r\n" +
        " * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A \r\n" +
        " * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL\r\n" +
        " * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR\r\n" +
        " * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF\r\n" +
        " * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS\r\n" +
        " * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE \r\n" +
        " * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER \r\n" +
        " * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT\r\n" +
        " * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.\r\n" +
        " *\r\n"+
        " *********************************************************************/\r\n\r\n" +
        "#ifndef __HTTPPRINT_H\r\n" +
        "#define __HTTPPRINT_H\r\n\r\n" +
        "#include \"TCPIP Stack/TCPIP.h\"\r\n\r\n" +
        "#if defined(STACK_USE_HTTP2_SERVER)\r\n\r\n" +
        "extern HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];\r\n" +
        "extern BYTE curHTTPID;\r\n\r\n" +
        "void HTTPPrint(DWORD callbackID);\r\n";
    String HTTPPRINT_H_MIDDLE =
        "\r\nvoid HTTPPrint(DWORD callbackID)\r\n" +
        "{\r\n" +
        "    switch(callbackID)\r\n" +
        "    {\r\n";
    String HTTPPRINT_H_FOOTER =
        "        default:\r\n" +
        "            // Output notification for undefined values\r\n" +
        "            TCPPutROMArray(sktHTTP, (ROM BYTE*)\"!DEF\", 4);\r\n" +
        "    }\r\n" +
        "    return;\r\n" +
        "}\r\n\r\n" +
        "void HTTPPrint_(void)\r\n" +
        "{\r\n" +
        "    TCPPut(sktHTTP, '~');\r\n" +
        "    return;\r\n" +
        "}\r\n\r\n#endif\r\n\r\n#endif\r\n";

    String HTTPPRINT_H_HEADER_UNIFIEDSTACK =
        "/*********************************************************************\r\n" +
        " * File Name: HTTPPrint.h\r\n" +
        " *\r\n" +
        " * Provides callback headers and resolution for user\'s custom\r\n" +
        " * HTTP Application.\r\n" +
        " * Processor: PIC24E, PIC24F, PIC24H, dsPIC30F, dsPIC33F, dsPIC33E,PIC32\r\n" +
        " * Compiler:  Microchip C30, C32,XC30,XC32\r\n" +
        " * \r\n" +
        " * This file is automatically generated by the MPFS Utility\r\n" +
        " * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n" +
        " *\r\n" +
        " * Software License Agreement\r\n" +
        " *\r\n" +
        " * Copyright (C) 2012 Microchip Technology Inc.  All rights\r\n" +
        " * reserved.\r\n" +
        " * Microchip licenses to you the right to use, modify, copy, and distribute\r\n" +
        " * software only embedded on a Microchip microcontroller or digital signal \r\n" +
        " * controller that is integrated into your product or third party product\r\n" +
        " * (pursuant to the sublicense terms in the accompanying license agreement)\r\n\r\n" +
        " * You should refer to the license agreement accompanying this \r\n" +
        " * Software for additional information regarding your rights and \r\n" +
        " * obligations.\r\n" +
        " *\r\n" +
        " * You should refer to the license agreement accompanying this \r\n" +
        " * Software for additional information regarding your rights and \r\n" +
        " * obligations.\r\n" +
        " *\r\n" +
        " * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED \"AS IS\" WITHOUT\r\n" +
        " * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT\r\n" +
        " * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A \r\n" +
        " * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL\r\n" +
        " * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR\r\n" +
        " * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF\r\n" +
        " * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS\r\n" +
        " * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE \r\n" +
        " * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER \r\n" +
        " * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT\r\n" +
        " * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.\r\n" +
        " *\r\n"+
        " *********************************************************************/\r\n\r\n" +
        "#ifndef __HTTPPRINT_H\r\n" +
        "#define __HTTPPRINT_H\r\n\r\n" +
        "#include \"tcpip/tcpip.h\"\r\n\r\n" +
        "#if defined(TCPIP_STACK_USE_HTTP_SERVER)\r\n\r\n" +
        "void TCPIP_HTTP_Print(HTTP_CONN_HANDLE connHandle,uint32_t callbackID);\r\n";
    String HTTPPRINT_H_MIDDLE_UNIFIED_STACK =
        "\r\nvoid TCPIP_HTTP_Print(HTTP_CONN_HANDLE connHandle,uint32_t callbackID)\r\n" +
        "{\r\n" +
        "TCP_SOCKET sktHTTP; \r\n" +
        "    switch(callbackID)\r\n" +
        "    {\r\n";
    String HTTPPRINT_H_FOOTER_UNIFIED_STACK =
        "        default:\r\n" +
        "            // Output notification for undefined values\r\n" +
        "            sktHTTP = TCPIP_HTTP_CurrentConnectionSocketGet(connHandle);\r\n" +
        "            TCPIP_TCP_ArrayPut(sktHTTP, (const uint8_t *)\"!DEF\", 4);\r\n" +
        "    }\r\n" +
        "    return;\r\n" +
        "}\r\n\r\n" +
        "void TCPIP_HTTP_Print_(HTTP_CONN_HANDLE connHandle)\r\n" +
        "{\r\n" +
        "    TCP_SOCKET sktHTTP = TCPIP_HTTP_CurrentConnectionSocketGet(connHandle);\r\n" +
        "    TCPIP_TCP_Put(sktHTTP, '~');\r\n" +
        "    return;\r\n" +
        "}\r\n\r\n#endif\r\n\r\n#endif\r\n";

    String HTTPPRINT_C_HEADER_UNIFIEDSTACK =
        "/*********************************************************************\r\n" +
        "HTTP Application callback source file \r\n" +
        "\r\n"+
        "Company:\r\n" +
        "   Microchip Technology Inc. \r\n\r\n" +
        "File Name:\r\n" +
        "   http_print.c\r\n\r\n" +
        "Description: \r\n" +
        "   Provides callback headers and resolution for user\'s custom\r\n" +
        "   HTTP Application.\r\n" +
        "   \r\n" +
        "   This file is automatically generated by the MPFS Utility\r\n" +
        "   ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n" +
        "   \r\n" +
        "*********************************************************************/\r\n\r\n" +
        "/*********************************************************************\r\n" +
        "Copyright (C) 2012-2018 Microchip Technology Inc. and its subsidiaries \r\n" +
        " Microchip Technology Inc. and its subsidiaries.\r\n" +
        " Subject to your compliance with these terms, you may use Microchip software\r\n" +
        " and any derivatives exclusively with Microchip products. It is your\r\n" +
        " responsibility to comply with third party license terms applicable to your\r\n" +
        " use of third party software (including open source software) that may\r\n" +
        " accompany Microchip software.\r\n\r\n" +
        " THIS SOFTWARE IS SUPPLIED BY MICROCHIP \"AS IS\". NO WARRANTIES, WHETHER\r\n" +
        " EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED\r\n" +
        " WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR\r\n" +
        " PURPOSE.\r\n" +
        " \r\n" +
        " IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,\r\n" +
        " INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND\r\n" +
        " WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS\r\n" +
        " BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE\r\n" +
        " FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN\r\n" +
        " ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,\r\n" +
        " THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.\r\n" +
        " *********************************************************************/\r\n\r\n" +
        "#include \"tcpip/tcpip.h\"\r\n\r\n" +
        "void TCPIP_HTTP_Print(HTTP_CONN_HANDLE connHandle,uint32_t callbackID);\r\n";
    String HTTPPRINT_C_MIDDLE_UNIFIED_STACK =
        "\r\nvoid TCPIP_HTTP_Print(HTTP_CONN_HANDLE connHandle,uint32_t callbackID)\r\n" +
        "{\r\n" +
        "    TCP_SOCKET sktHTTP; \r\n" +
        "    switch(callbackID)\r\n" +
        "    {\r\n";
    String HTTPPRINT_C_FOOTER_UNIFIED_STACK =
        "        default:\r\n" +
        "            // Output notification for undefined values\r\n" +
        "            sktHTTP = TCPIP_HTTP_CurrentConnectionSocketGet(connHandle);\r\n" +
        "            TCPIP_TCP_ArrayPut(sktHTTP, (const uint8_t *)\"!DEF\", 4);\r\n" +
        "    }\r\n" +
        "    return;\r\n" +
        "}\r\n\r\n" +
        "void TCPIP_HTTP_Print_myVariable(HTTP_CONN_HANDLE connHandle)\r\n" +
        "{\r\n" +
        "    TCP_SOCKET sktHTTP = TCPIP_HTTP_CurrentConnectionSocketGet(connHandle);\r\n" +
        "    TCPIP_TCP_Put(sktHTTP, '~');\r\n" +
        "    return;\r\n" +
        "}\r\n";

/*
 * Collect the Dynamic variable in the HTTPPrint.idx file.
 */
    public DynVar(String path,boolean ifTcpipVersion6used)
    {
        this.projectDir = path;
        vars = new LinkedList<DynamicVariable>();
        tcpipVersion6used = ifTcpipVersion6used;
        // Read previous index file if it exists.
        File file_exists;
        FileInputStream inputFile;
        try
        {
            if(tcpipVersion6used)
            {
                file_exists = new File(projectDir + "http_print.idx");
            }
            else
            {
                file_exists = new File(projectDir + "HTTPPrint.idx");
            }
            if(file_exists.exists() && file_exists.length()>0)
            {
                if(tcpipVersion6used)
                {
                    inputFile = new FileInputStream(projectDir + "http_print.idx");
                }
                else
                {
                    inputFile = new FileInputStream(projectDir + "HTTPPrint.idx");
                }
                DataInputStream in = new DataInputStream(inputFile);
                BufferedReader fin = new BufferedReader(new InputStreamReader(in));
                String s = fin.readLine();

                if (!s.contains("|"))
                {
                    while (s != null)
                    {
                        DynamicVariable dv = new DynamicVariable(s);
                        vars.add(dv);
                        s = fin.readLine();
                    }
                }
                fin.close();
            }
        }
        catch(IOException e)
        {
            // do nothing...just won't have old index information
        }
    }

    /// <summary>
    /// Parses and indexes a file for dynamic variables
    /// </summary>
    /// <param name="file">The MPFSFileRecord to parse</param>
    /// <returns>An MPFSFileRecord of indexes, or null if no variables were found</returns>
    public MPFSFileRecord Parse(MPFSFileRecord file,StringBuilder strLine)
    {
        int dynVarCntr=0;
        //Vector<Byte> resizeArray = new Vector(8,8);
        ByteArrayOutputStream resizeArray = new ByteArrayOutputStream();
        Matcher matches = parser.matcher(strLine);

        while(matches.find())
        {
            int i = GetIndex(matches.group().replace(" ","").replace("~",""));

            resizeArray.write((byte)matches.start());
            resizeArray.write((byte)(matches.start()>>8));
            resizeArray.write((byte)(matches.start()>>16));
            resizeArray.write((byte)(matches.start()>>24));
            resizeArray.write((byte)i);
            resizeArray.write((byte)(i>>8));
            resizeArray.write((byte)(i>>16));
            resizeArray.write((byte)(i>>24));

            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 0));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 8));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 16));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 24));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 0));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 8));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 16));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 24));

            file.dynVarCntr = ++dynVarCntr;
            offSetCounter = offSetCounter + 8;
        }

        if(parseItrtn == (int)0x0)
        {
             file.fileRecordOffset = (int)0x0;
             offSetCounter = (int)0x0;
        }
        else
        {
              file.fileRecordOffset=tempFileRcrdLen;
        }
        if(file.dynVarCntr != 0)
        {
            file.fileRecordLength = 4 /* 4 bytes for file record length itself*/
                                    + 2 /*To store the hasIndex/isZipped flag*/
                                    //+(UInt32)file.FileName.Length
                                    + file.dynVarCntr * 8;

            tempFileRcrdLen += file.fileRecordLength;

            parseItrtn++;
        }

        // Determine if any matches were made
        if (resizeArray.size() == 0)
        {
            return null;
        }
        else
        {
            // Set up new file record
            MPFSFileRecord idxFile = new MPFSFileRecord();
            idxFile.SetFileName("");   //.FileName = "";
            idxFile.SetFiledate(file.fileDate);
            idxFile.isIndex = true;
            idxFile.data = resizeArray.toByteArray();
            idxFile.fileSizeLen = resizeArray.size();
            return idxFile;
        }
    }

    /// <summary>
    /// Writes out HTTPPrint.h and HTTPPrint.idx if necessary
    /// </summary>
    /// <returns>TRUE if the files were written, FALSE if no changes are needed</returns>
    public boolean WriteIndices()
    {
        // Determine if an update is necessary
        boolean isChanged = false;
        File httpFileIdx;
        String temp_str;

        for(DynamicVariable dv : vars)
        {
            if ((dv.getWasUsed() && dv.getCount() == 0) ||
                (!dv.getWasUsed() && dv.getCount() != 0))
            {
                isChanged = true;
                break;
            }
        }
        if (!isChanged)
        {
            return false;
        }

        // Write out HTTPPrint.idx
        if(tcpipVersion6used)
        {
            httpFileIdx = new File(projectDir +"http_print.idx");
        }
        else
        {
            httpFileIdx = new File(projectDir +"HTTPPrint.idx");
        }
        try{
        FileOutputStream file_output = new FileOutputStream(httpFileIdx);
        DataOutputStream data_out = new DataOutputStream (file_output);
        BufferedWriter fout = new BufferedWriter(new OutputStreamWriter(data_out));

        for(DynamicVariable dv : vars)
        {
            if (dv.getCount() > 0)
            {
                fout.write('+');
            }
            fout.write(dv.GetName());
            fout.write('\n');
        }
        fout.flush();
        fout.close();

        // Begin writing HTTPPrint.h
        if(tcpipVersion6used)
        {
            //file_output = new FileOutputStream(projectDir + "http_print.h");
            file_output = new FileOutputStream(projectDir + "http_print.c");
        }
        else
        {
            file_output = new FileOutputStream(projectDir + "HTTPPrint.h");
        }
        data_out = new DataOutputStream (file_output);
        fout = new BufferedWriter(new OutputStreamWriter(data_out));
        if(tcpipVersion6used)
        {
            //fout.write(HTTPPRINT_H_HEADER_UNIFIEDSTACK);
            fout.write(HTTPPRINT_C_HEADER_UNIFIEDSTACK);
        }
        else
        {
            fout.write(HTTPPRINT_H_HEADER);
        }

        // Write the prototypes
        List<String> prototypes = new ArrayList<String>();
        Pattern rGetParts = Pattern.compile("([A-Za-z0-9_]{0,40})(\\(([A-Za-z0-9_,]*)\\))?");
        for(DynamicVariable dv : vars)
        {
            if (dv.GetName().startsWith("inc:") || dv.getCount() == 0)
            {
                continue;
            }
            Matcher m = rGetParts.matcher(dv.GetName());
            if(m.find()){
            if (prototypes.contains(m.group(1)))
            {
                continue;
            }

            // Add the prototype
            prototypes.add(m.group(1));
            if(tcpipVersion6used)
            {
                temp_str = "void TCPIP_HTTP_Print_" + m.group(1) + "(";
            }
            else
            {
                temp_str = "void HTTPPrint_" + m.group(1) + "(";
            }
            fout.write(temp_str);
            if(m.group(3) != null)
            {
                if(tcpipVersion6used)
                {
                    fout.write("HTTP_CONN_HANDLE connHandle,");
                }
                if(m.groupCount() == 3 && m.group(3).length() > 0)
                {
                    int numParams = m.group(3).split(",").length;
                    for (int i = 0; i < numParams - 1; i++)
                    {
                        if(tcpipVersion6used)
                        {
                            fout.write("uint16_t,");
                        }
                        else
                        {
                            fout.write("WORD,");
                        }
                    }
                    if(tcpipVersion6used)
                    {
                        fout.write("uint16_t");
                    }
                    else
                    {
                        fout.write("WORD");
                    }
                }
            }
            else
            {
                 if(tcpipVersion6used)
                 {
                    fout.write("HTTP_CONN_HANDLE connHandle");
                 }
                 else
                 {
                    fout.write("void");
                 }
            }
            fout.write(");\r\n");
            }
        }

        // Write the function itself
        if(tcpipVersion6used)
        {
           // fout.write(HTTPPRINT_H_MIDDLE_UNIFIED_STACK);
            fout.write(HTTPPRINT_C_MIDDLE_UNIFIED_STACK);
        }
        else
        {
            fout.write(HTTPPRINT_H_MIDDLE);
        }
        int index = 0;
        for(DynamicVariable dv : vars)
        {
            if (dv.getCount() == 0)
            {
                index++;
                continue;
            }
            temp_str  = "        case 0x" + String.format("%08x",index++) + ":\r\n";
            fout.write(temp_str);

            // Write the actual case statement
            if(dv.GetName().startsWith("inc:"))
            {
                if(tcpipVersion6used)
                {
                    temp_str = "\t\t\tTCPIP_HTTP_FileInclude(connHandle,(const uint8_t *)\"" + dv.GetName().substring(4) + "\");\r\n\t\t\tbreak;\r\n";
                }
                else
                {
                    temp_str = "\t\t\tHTTPIncFile((ROM BYTE*)\"" + dv.GetName().substring(4) + "\");\r\n\t\t\tbreak;\r\n";
                }
                fout.write(temp_str);
            }
            else
            {
                if(tcpipVersion6used)
                {
                    if(!dv.GetName().endsWith(")"))
                    {
                        temp_str = "\t\t\tTCPIP_HTTP_Print_" + dv.GetName();
                        fout.write(temp_str);
                        fout.write("(connHandle)");
                    }
                    else
                    {
                        temp_str = dv.GetName();
                        temp_str = temp_str.replace("(", "(connHandle,");
                        temp_str = "\t\t\tTCPIP_HTTP_Print_" + temp_str;
                        fout.write(temp_str);
                    }
                }
                else
                {
                    temp_str = "\t\t\tHTTPPrint_" + dv.GetName();
                    fout.write(temp_str);
                    if(!dv.GetName().endsWith(")"))
                    {
                        fout.write("()");
                    }
                }

                fout.write(";\r\n\t\t\tbreak;\r\n");
            }
        }

        // Write the footer part
        if(tcpipVersion6used)
        {
            //fout.write(HTTPPRINT_H_FOOTER_UNIFIED_STACK);
            fout.write(HTTPPRINT_C_FOOTER_UNIFIED_STACK);
        }
        else
        {
            fout.write(HTTPPRINT_H_FOOTER);
        }
        fout.flush();
        fout.close();
        }catch (IOException e){}
        return true;
    }

    /// <summary>
    /// Finds the index of a dynamic variable, or creates a new one
    /// </summary>
    /// <param name="name"></param>
    /// <returns>The index of the dynamic variable</returns>
    private int GetIndex(String name)
    {
        int count = 0;
        // Search for the dynamic variable
        DynamicVariable dv = new DynamicVariable(name);

        int i = vars.indexOf(dv);
        // If not found, add a new one
        if (i == -1)
        {
            vars.add(dv);
            i = vars.size()-1;
        }
        // Mark as used and return the index
        count = vars.get(i).getCount();
        vars.get(i).setCount(++count);

        return i;
    }
}

/*
 * Dynamic variable class to count and find out the instance how many times
 * it is being used.
 */
class DynamicVariable
{
    private String name;
    private boolean wasUsed;
    private int count;

    /// <summary>
    /// Gets or sets the name of this DynamicVariable
    /// </summary>
    public String GetName()
    {
        return this.name;
    }

    public void SetName(String value)
    {
        this.name = value;
    }

    /// <summary>
    /// Indicates if this specific instance was previously used
    /// </summary>
    public boolean getWasUsed()
    {
       return this.wasUsed;
    }
    public void setWasUsed(boolean value)
    {
        this.wasUsed = value;
    }
    /// <summary>
    /// Indicates how many times this instance is used
    /// </summary>
    public int getCount()
    {
       return this.count;
    }

    public void setCount(int value)
    {
       this.count = value;
    }
    private long _offsetCntr = 0;
    public long getOffsetCntr()
    {
        return this._offsetCntr;
    }

    public void setOffsetCntr(long value)
    {
         this._offsetCntr = value;
    }

    public DynamicVariable(String name)
    {
        String regEx = "[\\ \\+]";
        this.wasUsed = name.startsWith("+");
        //Pattern pattern = Pattern.compile(regEx);
        //Matcher match = pattern.matcher(name);
        //if(match.find())
        //    this.name = pattern.matcher(name).replaceFirst("");
        //else
        this.name = name.replaceFirst(regEx,"");
        //this.name = matches.group().replaceFirst(regEx,"");
        this.count = 0;
    }

    public boolean equals(Object obj)
    {
        if (obj instanceof DynamicVariable)
        {
            return ((DynamicVariable)obj).GetName().contentEquals(this.name);
        }
        else
        {
            return false;
        }
    }

    public int hashCode()
    {
        return this.name.hashCode();
    }
}
